/*
	Driver para joystick de playstation ID=0x41 e 0x73
	Esta biblioteca somente lê valores digitais dos botões, não faz controle de vibração ou configurações
*/

#include "joyps.h"

static volatile int joy;

// #################################################################################################################
// FUNÇÕES GLOBAIS
// #################################################################################################################

//------------------------------------------------------------------------------------------------------------------
// Descrição: Configura o pino CHIP SELECT
//------------------------------------------------------------------------------------------------------------------

// O joystick trabalha com CPOL=1 e CPHA=1.
void joy_Init(void) {
	joyps_SetupPorts();	// Configurar o pino CS
    joyps_Disable();
    joy = 0;
}

// retonra com o valor da tecla pressionada.
int joy_Read(void) {
	int j = joy; // retorna com o valor da tecla pressionada
	joy = 0; // sinaliza que não tem mais tecla sendo pressionada
	return j;
}

static u8 __swap(u8 v) {
	#if defined(usesSSP) // bus ssp não tem transmissão LSB
	u8 aux = 0;
	int x; for (x=0; x < 8; x++) if ((v&_BV(x)) > 0) aux |= _BV(7-x);
	return aux;
	#else
	return v;
	#endif
}

static int __joy_ReadControls(int* ctrl ) {
	joyps_Enable();
	joyps_TransferByte(__swap(0x1)); // Envio o byte para inicializar transferencia ao controle PS1
	int id = __swap(joyps_TransferByte(__swap(0x42))); // Envio o byte de quesito de dados do controle PS1 e recebo o ID do controle
	joyps_TransferByte(0);	// Envio qualquer valor para o controle para receber dele o indicador de inicio de transmissão.
	int b1 = __swap(~joyps_TransferByte(0)); // Envio qualquer valor para o controle para receber dele o primeiro comando que representa os estados dos botões.
	int b2 = __swap(~joyps_TransferByte(0)); // Envio qualquer valor para o controle para receber dele o segundo comando que representa os estados dos botões.
	// somente para joystick com suporte analógico.
	//	int a1 = __swap(~joyps_TransferByte(0));
	//	int a2 = __swap(~joyps_TransferByte(0));
	//	int a3 = __swap(~joyps_TransferByte(0));
	//	int a4 = __swap(~joyps_TransferByte(0));
	joyps_Disable();

	*ctrl = (b1 << 8) | b2;
	return id;
}

// Chamar esta função a cada 1ms
// ATENÇÃO: O acesso SPI ao joystick foge do padrão dos demais dispositivos que usamos.
//			Caso isto está usando o mesmo barramento SPI para acessar outros dipositivos que são de padrões de acesso
//				diferentes é preciso utiliza uma subchamada da rotina joy_Tick trocando as condições de acesso:
//			Exemplo:
//				void joy_Tick2(void) {
//					ssp1_Init(SSP0_MASTER, SSP0_CPOL_H|SSP0_CPHA_H|SSP0_DSS_8); // inicar o barramento SPI a 400Khz
//				    joy_Tick();
//					ssp1_Init(SSP0_MASTER, SSP0_STANDARD); // inicar o barramento SPI a 400Khz
//				}
void joy_Tick(void) {
	// LEITURA DO JOYSTICK a cada 16ms
	// 	Ler a cada 16ms já é o suficiente para uma boa resposta
	static volatile uint timeRead = 0;
	if (timeRead) timeRead--;
	if (timeRead == 0) {
		timeRead = 16;
		int buttons;
		__joy_ReadControls(&buttons);
		if (buttons > 0) joy = buttons;
	}
}
